package edu.rpi.tw.escience.stargazer.rest;

import edu.rpi.tw.escience.stargazer.server.SimpleException;
import edu.rpi.tw.escience.stargazer.server.StarGazer;
import edu.rpi.tw.escience.stargazer.server.StarGazerContext;
import org.jdom.Content;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.Text;
import org.jdom.output.XMLOutputter;
import org.openrdf.model.Literal;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.model.vocabulary.OWL;
import org.openrdf.model.vocabulary.RDF;
import org.openrdf.model.vocabulary.RDFS;
import org.openrdf.repository.RepositoryException;
import org.restlet.data.MediaType;

import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;
import java.util.Set;

/**
 * Author: josh
 * Date: Apr 27, 2009
 * Time: 10:56:24 PM
 */
public class CelestialObjectHTTPRepresentation extends CelestialObjectRepresentation {
    static final Namespace XHTML_NS = Namespace.getNamespace("http://www.w3.org/1999/xhtml");
    private final String serverURL;

    public CelestialObjectHTTPRepresentation(final URI resourceURI,
                                             final StarGazerContext context,
                                             final String serverURL) {
        super(resourceURI, context, MediaType.TEXT_HTML);
        this.serverURL = serverURL;
    }

    public void write(final OutputStream out) throws IOException {
        Document d = new Document();

        Element root = new Element("html", XHTML_NS);
        d.setRootElement(root);

        Element body = new Element("body", XHTML_NS);
        root.addContent(body);

        Element headerP = new Element("p", XHTML_NS);
        body.addContent(headerP);
        headerP.addContent(resourceURI.getLocalName());

        Element tableP = new Element("p", XHTML_NS);
        body.addContent(tableP);

        Element table = new Element("table", XHTML_NS);
        tableP.addContent(table);
        table.setAttribute("border", "1");

        Element thead = new Element("thead", XHTML_NS);
        table.addContent(thead);
        Element titles = new Element("tr", XHTML_NS);
        thead.addContent(titles);
        Element td1 = new Element("td", XHTML_NS);
        titles.addContent(td1);
        td1.addContent("Property");
        Element td2 = new Element("td", XHTML_NS);
        titles.addContent(td2);
        td2.addContent("Value");

        Element tbody = new Element("tbody", XHTML_NS);
        table.addContent(tbody);

        Map<URI, Set<Value>> propertyValues;
        try {
            propertyValues = getPropertyValues();
        } catch (RepositoryException e) {
            new SimpleException(e).logError();
            throw new IOException("failed to serialize resource");
        }

        for (URI p : propertyValues.keySet()) {
            Element tr = new Element("tr", XHTML_NS);
            tbody.addContent(tr);

            Element leftTd = new Element("td", XHTML_NS);
            tr.addContent(leftTd);
            Element rightTd = new Element("td", XHTML_NS);
            tr.addContent(rightTd);

            leftTd.addContent(formatPropertyURI(p));

            boolean first = true;
            for (Value o : propertyValues.get(p)) {
                if (first) {
                    first = false;
                } else {
                    //rightTd.addContent(new Element("br", XHTML_NS));
                    rightTd.addContent(", ");
                }

                rightTd.addContent(formatObjectValue(o, serverURL));
            }
        }

        Element validatorP = new Element("p", XHTML_NS);
        body.addContent(validatorP);
        
        Element a = new Element("a", XHTML_NS);
        validatorP.addContent(a);
        a.setAttribute("href", "http://validator.w3.org/check/referer");
        Element img = new Element("img", XHTML_NS);
        a.addContent(img);
        img.setAttribute("src", "http://www.w3.org/Icons/valid-xhtml10");
        img.setAttribute("alt", "Validate XHTML");
        img.setAttribute("height", "31");
        img.setAttribute("width", "88");

        /*
       <a href="http://validator.w3.org/check/referer">
       <img src="http://www.w3.org/Icons/valid-xhtml10" alt="Validate XHTML" height="31" width="88"/>
   </a>
        */


        XMLOutputter putter = new XMLOutputter();
        putter.output(d, out);
    }

    private String formatPropertyURI(final URI uri) {
        if (uri.getNamespace().equals(RDF.NAMESPACE)) {
            return "rdf:" + uri.getLocalName();
        } else if (uri.getNamespace().equals(RDFS.NAMESPACE)) {
            return "rdfs:" + uri.getLocalName();
        } else if (uri.getNamespace().equals(OWL.NAMESPACE)) {
            return "owl:" + uri.getLocalName();
        } else if (uri.getNamespace().equals(StarGazer.NS)) {
            return "sg:" + uri.getLocalName();
        } else {
            return "<" + uri + ">";
        }
    }

    private Content formatObjectValue(final Value v,
                                      final String serverURL) {
        if (v instanceof Literal) {
            // Note: data type and language information is discarded.
            return new Text(((Literal) v).getLabel());
        } else if (v instanceof URI) {
            return localLink((URI) v, ((URI) v).getLocalName(), serverURL);
        } else {
            return new Text("[resource has unhandled type]");
        }
    }

    public static Element localLink(final URI u,
                                    final String label,
                                    final String serverURL) {
        Element a = new Element("a", XHTML_NS);
        a.addContent(label);

        if (u.getNamespace().equals(StarGazer.NS)) {
            a.setAttribute("href", u.getLocalName());
        } else {
            a.setAttribute("href", u.toString());
        }

        return a;
    }
}
